/****************************************************************************
*					ClusterGraph
*
*	Description:	A class for representing Cluster Graph (CG) of a given
*					Probabilistic Graphical Model (PGM)
*
****************************************************************************/

#ifndef _ClusterGraph_H
#define _ClusterGraph_H

#include <vector>
#include <map>
#include "Feature.h"
#include "PGMStruct.h"
#include "DomainFeatures.h"


// Defining Domain Neighbors and Domain Belief
struct DomainDescr {
	// vector of sepSet IDs
	std::vector <unsigned int> neighbors;
	// belief for this domain
	std::vector <float> belief;
};

struct SepSet {
	// last sent messages from one parent to another
	std::vector<float> muOneTwo;
	std::vector<float> muTwoOne;
	// shows if the last message were sent by parent one (in this case sepSet belief == muOneTwo, otherwise == muTwoOne)
	bool direction;
	// first parent of this sepSet - domain with one variable
	unsigned int parOne;
	// second parent of this sepSet - domain with at least one variable (typically >= 2)
	unsigned int parTwo;
	// common variable for two parents
	unsigned int commonVar;
};

struct pathElem {
	unsigned int domID;
	std::vector <bool> coveredVars;
	std::vector <unsigned int> connectedElems;
	std::vector <unsigned int> sepSetIDs;
};

class ClusterGraph {
  private:

  protected:

  public:

	/* Data */
	  // Separation sets vectors (ordered by sepSetID)
	std::vector < SepSet > sepSets;
	  // Describing domains in PGM augmenting them with DomainDescr
	std::vector < DomainDescr > domainDescriptions;
	  // IDs of domains that contain one variable only
	std::vector <int> oneVarDomain;
	  // Partition fucntion value
	float Z;


	/* Functions */
	  // Standard constructor - empty one
	ClusterGraph();
      
	  // Standard destructor - empty one
    ~ClusterGraph();

	  // Constructs a cluster graph for a given PGM
	int initStructure (PGMStruct& pgmStruct);

	  // Removes all elements in internal variables
	void clear (void);

	static inline void moveValues (std::vector<unsigned int>& vals, int& moveFromPos, std::vector<unsigned int>& varIDs, std::vector <unsigned int>& numVals) {
		while (moveFromPos >=0) {
			vals[moveFromPos]++;
			if (vals[moveFromPos] < numVals[varIDs[moveFromPos]]) break;
			vals[moveFromPos] = 0;
			moveFromPos--; } }
	
}; // end of class

#endif // _ClusterGraph_H
